package com.example.handler;

import org.springframework.stereotype.Component;

import com.example.constant.MessageDecoderConstant;
import com.example.constant.ServerConstant;
import com.example.service.CallHandler;
import com.example.service.CountHandler;
import com.example.service.ErrorHandler;
import com.example.service.HeartBeatHandler;
import com.example.service.MessageDecoder;
import com.example.service.RemoteElectricHandler;
import com.example.service.SendHandler;
import com.example.service.ShakeHandHandler;
import com.example.service.TimeSynHandler;
import com.example.service.UHandler;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;

@Component
public class Server {

	CallHandler callHandler;
	HeartBeatHandler heartBeatHandler;
	ShakeHandHandler shakeHandHandler;
	MessageDecoder decoder;

	private EventLoopGroup boss;
	private EventLoopGroup work;
	private ServerBootstrap b;

	public Server() {
		// TODO Auto-generated constructor stub
		boss = new NioEventLoopGroup();
		work = new NioEventLoopGroup();
		b = new ServerBootstrap();
		callHandler = new CallHandler();
		heartBeatHandler = new HeartBeatHandler();
		shakeHandHandler = new ShakeHandHandler();
		decoder = new MessageDecoder(MessageDecoderConstant.MAX_FRAME_LENGTH,
				MessageDecoderConstant.LENGTH_FIELD_OFFSET, MessageDecoderConstant.LENGTH_FIELD_LENGTH,
				MessageDecoderConstant.LENGTH_ADJUSTMENT, MessageDecoderConstant.INITIAL_BYTES_TO_STRIP);
	}

	public void start() throws InterruptedException {
		try {
			b.group(boss, work).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, 100)
					.handler(new LoggingHandler()).childHandler(new ChannelInitializer<SocketChannel>() {

						@Override
						protected void initChannel(SocketChannel ch) throws Exception {
							// TODO Auto-generated method stub
							ChannelPipeline pipeline = ch.pipeline();
							pipeline.addLast("send", new SendHandler());

							pipeline.addLast("decode",
									new MessageDecoder(MessageDecoderConstant.MAX_FRAME_LENGTH,
											MessageDecoderConstant.LENGTH_FIELD_OFFSET,
											MessageDecoderConstant.LENGTH_FIELD_LENGTH,
											MessageDecoderConstant.LENGTH_ADJUSTMENT,
											MessageDecoderConstant.INITIAL_BYTES_TO_STRIP));
							// 监听是否电桩是否还存活，时限70，理论要求60，多出10防止报文延时
							pipeline.addLast("PingHandler", new IdleStateHandler(70, 0, 0));
							// 握手报文监听
							pipeline.addLast(new ShakeHandHandler());
							// U帧监听
							pipeline.addLast(new UHandler());
							// 总召监听
							pipeline.addLast(new CallHandler());
							// 计数量监听
							pipeline.addLast(new CountHandler());
							// 时间同步监听
							pipeline.addLast(new TimeSynHandler());
							// 远程监听
							pipeline.addLast(new RemoteElectricHandler());
							// 错误监听
							pipeline.addLast(new ErrorHandler());

						}

					});
			ChannelFuture f = b.bind(ServerConstant.PORT).sync();
			f.channel().closeFuture().sync();
		} finally {
			boss.shutdownGracefully();
			work.shutdownGracefully();
		}
	}

	public static void main(String[] args) throws InterruptedException {
		Server server = new Server();
		server.start();
	}

}
